<?php
/**
 * utilForm
 *
 * 폼생성 클래스
 *
 * 메소드 파라미터 중 $aAttr 에 해당되는 부분에는 배열형태로 '속성명' => '값' 을 할당하도록 합니다.
 * <code>
 * utilForm::text(array('id' => 'test_id', 'class' => 'test_class'));
 * </code>
 *
 *
 * 셀렉트형의 경우 여러개의 파라미터를 받게 되는데 아래 예를 살펴봅시다.
 *
 * 1. 일반 출력
 * <code>
 * $aAttr = array(
 *  'id' => 'test_select'
 * );
 *
 * $aOption = array(
 *  '에이' => 'a',
 *  '비' => 'b'
 * );
 *
 * utilForm::select($aAttr, $aOption);
 *
 * //결과
 * <select id="test_select">
 *  <option value="a">에이</option>
 *  <option value="b">비</option>
 * </select>
 * </code>
 *
 *
 * 2. 그룹별 출력
 * <code>
 * $aAttr = array(
 *  'id' => 'test_select'
 * );
 *
 * $aOption = array(
 *  '에이그룹' => array(
 *      '에이-1' => 'a-1',
 *      '에이-2' => 'a-2'
 *  ),
 *  '비그룹' => array(
 *      '비-1' => 'b-1',
 *      '비-2' => 'b-2'
 *  )
 * );
 *
 * utilForm::select($aAttr, $aOption);
 *
 * //결과
 * <select id="test_select">
 *  <optgroup label="에이그룹">
 *      <option value="a-1">에이-1</option>
 *      <option value="a-2">에이-2</option>
 *  </optgroup>
 *  <optgroup label="비그룹">
 *      <option value="b-1">비-1</option>
 *      <option value="b-2">비-2</option>
 *  </optgroup>
 * </select>
 * </code>
 *
 *
 * 3. 다중선택 출력
 * <code>
 * $aAttr = array(
 *  'id' => 'test_select'
 * );
 *
 * $aOption = array(
 *  '에이' => 'a',
 *  '비' => 'b',
 *  '씨' => 'c'
 * );
 *
 * utilForm::select($aAttr, $aOption, array('a', 'b'), true);
 *
 * //결과
 * <select id="test_select" multiple="multiple">
 *  <option value="a" selected="selected">에이</option>
 *  <option value="b" selected="selected">비</option>
 *  <option value="c">씨</option>
 * </select>
 * </code>
 *
 * @package util
 * @author  Platform Team
 */

class utilForm
{
    /**
     * 폼 시작 태그 생성
     *
     * @param array $aAttr        (속성배열)
     * @param boolean $isMultipart  (파일업로드 여부 : 기본 false)
     * @return string
     */
    public static function begin($aAttr=array(), $isMultipart=false)
    {
        $aAttr['method'] = !empty($aAttr['method']) ? $aAttr['method'] : 'POST';

        $aAddAttr = $isMultipart === true ? array('enctype' => 'multipart/form-data') : array();
        $sAttribute = self::parseAttribute($aAttr, $aAddAttr);

        return '<form' . $sAttribute . '>';
    }

    /**
     * 폼 닫기 태그 생성
     *
     * @return string
     */
    public static function end()
    {
        return '</form>';
    }

    /**
     * 텍스트형 폼 생성
     *
     * @param array $aAttr    (속성배열)
     * @param string $sValue   (값)
     * @return string
     */
    public static function text($aAttr=array(), $sValue='')
    {
        $sAttribute = self::parseAttribute($aAttr, array('value' => $sValue, 'type' => 'text'));

        return self::input($sAttribute);
    }

    /**
     * 패스워드형 폼 생성
     *
     * @param array $aAttr    (속성배열)
     * @param string $sValue   (값)
     * @return string
     */
    public static function password($aAttr=array(), $sValue='')
    {
        $sAttribute = self::parseAttribute($aAttr, array('value' => $sValue, 'type' => 'password'));

        return self::input($sAttribute);
    }

    /**
     * 히든형 폼 생성
     *
     * @param array $aAttr    (속성배열)
     * @param string $sValue   (값)
     * @return string
     */
    public static function hidden($aAttr=array(), $sValue='')
    {
        $sAttribute = self::parseAttribute($aAttr, array('value' => $sValue, 'type' => 'hidden'));

        return self::input($sAttribute);
    }

    /**
     * 파일형 폼 생성
     *
     * @param array $aAttr    (속성배열)
     * @return string
     */
    public static function file($aAttr=array())
    {
        $sAttribute = self::parseAttribute($aAttr, array('type' => 'file'));

        return self::input($sAttribute);
    }

    /**
     * 셀렉트형 폼 생성
     *
     * @param array $aAttr    (속성배열)
     * @param array $aOption  (옵션태그에 해당되는 배열)
     * @param mixed $mValue   (선택될 값 - 다중선택일 경우 배열로 할당)
     * @param boolean $isMulti  (다중선택여부 : 기본 false)
     * @return string
     */
    public static function select($aAttr=array(), $aOption=array(), $mValue=array(), $isMulti=false)
    {
        if (!is_array($aOption)) {
            $aOption = array();
        }

        if (!is_array($mValue)) {
            $mValue = array($mValue);
        }

        $aAddAttr = $isMulti === true ? array('multiple' => 'multiple') : array();
        $sAttribute = self::parseAttribute($aAttr, $aAddAttr);

        $sResult = '<select' . $sAttribute . '>';
        $sResult.= self::parseSelectOption($aOption, $mValue);
        $sResult.= '</select>';

        return $sResult;
    }

    /**
     * 체크박스형 폼 생성
     *
     * @param array $aAttr        (속성배열)
     * @param string $sValue       (값)
     * @param boolean $isChecked    (체크여부 : 기본 false)
     * @return string
     */
    public static function checkbox($aAttr=array(), $sValue='', $isChecked=false)
    {
        $aAddAttr = array('value' => $sValue, 'type' => 'checkbox');

        if ($isChecked === true) {
            $aAddAttr['checked'] = 'checked';
        }

        $sAttribute = self::parseAttribute($aAttr, $aAddAttr);

        return self::input($sAttribute);
    }

    /**
     * 라디오형 폼 생성
     *
     * @param array $aAttr        (속성배열)
     * @param string $sValue       (값)
     * @param boolean $isChecked    (체크여부 : 기본 false)
     * @return string
     */
    public static function radio($aAttr=array(), $sValue='', $isChecked=false)
    {
        $aAddAttr = array('value' => $sValue, 'type' => 'radio');

        if ($isChecked === true) {
            $aAddAttr['checked'] = 'checked';
        }

        $sAttribute = self::parseAttribute($aAttr, $aAddAttr);

        return self::input($sAttribute);
    }

    /**
     * 멀티텍스트형 폼 생성
     *
     * @param array $aAttr    (속성배열)
     * @param string $sValue   (값)
     * @return string
     */
    public static function textarea($aAttr, $sValue='')
    {
        $sAttribute = self::parseAttribute($aAttr);

        return '<textarea' . $sAttribute . '>' . self::entities($sValue) . '</textarea>';
    }

    /**
     * 라벨형 폼 생성
     *
     * @param string $sName    (노출될 라벨명)
     * @param string $sFor     (연결할 엘리먼트 아이디)
     * @param array $aAttr    (속성배열)
     * @return string
     */
    public static function label($sName, $sFor='', $aAttr=array())
    {
        $sAttribute = self::parseAttribute($aAttr, array('for' => $sFor));

        return '<label' . $sAttribute . '>' . $sName . '</label>';
    }

    /**
     * 버튼형 폼 생성
     *
     * @param string $sName    (노출될 버튼명)
     * @param array $aAttr    (속성배열)
     * @return string
     */
    public static function button($sName='', $aAttr=array())
    {
        $sAttribute = self::parseAttribute($aAttr, array('type' => 'button'));

        return '<button' . $sAttribute . '>' . $sName . '</button>';
    }

    /**
     * 리셋버튼형 폼 생성
     *
     * @param string $sName    (노출될 버튼명)
     * @param array $aAttr    (속성배열)
     * @return string
     */
    public static function reset($sName='', $aAttr=array())
    {
        $sAttribute = self::parseAttribute($aAttr, array('type' => 'reset', 'value' => $sName));

        return self::input($sAttribute);
    }

    /**
     * 서브밋버튼형 폼 생성
     *
     * @param string $sName    (노출될 버튼명)
     * @param array $aAttr    (속성배열)
     * @return string
     */
    public static function submit($sName='', $aAttr=array())
    {
        $sAttribute = self::parseAttribute($aAttr, array('type' => 'submit', 'value' => $sName));

        return self::input($sAttribute);
    }

    /**
     * 이미지 폼 생성
     *
     * @param string $sSrc     (노출될 이미지  URL)
     * @param array $aAttr    (속성배열)
     * @return string
     */
    public static function image($sSrc='', $aAttr=array())
    {
        $sAttribute = self::parseAttribute($aAttr, array('type' => 'image', 'src' => $sSrc));

        return self::input($sAttribute);
    }

    /**
     * 배열형태로 들어온 속성값들을 모두 하나의 배열로 합친다.
     *
     * @param array $aAttr    (기본 속성)
     * @param array $aAddAttr (추가 속성)
     */
    public static function attrMerge($aAttr=array(), $aAddAttr=array())
    {
        if (!is_array($aAttr)) {
            $aAttr = array();
        }

        if (!is_array($aAddAttr)) {
            $aAddAttr = array();
        }

        $aAttr = array_merge($aAttr, $aAddAttr);

        return $aAttr;
    }

    /**
     * INPUT 태그 생성
     *
     * @param string $sAttribute
     * @return string
     */
    protected static function input($sAttribute)
    {
        return '<input' . $sAttribute . ' />';
    }

    /**
     * Select 태그내 옵션 엘리먼트 생성
     *
     * @param array $aOption
     * @param mixed $mValue
     * @return string
     */
    protected static function parseSelectOption($aOption, $mValue)
    {
        if (empty($aOption)) return '';

        $sResult = "\n";

        foreach ($aOption as $key => $value) {

            if (is_array($value)) {

                $sResult .= '<optgroup label="' . $key . '">';
                $sResult .= self::parseSelectOption($value, $mValue);
                $sResult .= '</optgroup>' . "\n";

            } else {

                $sSelected = in_array($value, $mValue) ? ' selected="selected"' : '';
                $sResult .= '<option value="' . $value . '"' . $sSelected . '>' . $key . '</option>' . "\n";

            }

        }

        return $sResult;
    }

    /**
     * 배열로 들어온 속성들을 완성된 스트링으로 교체
     *
     * @param array $aAttr
     * @param array $aAddAttr
     * @return string
     */
    protected static function parseAttribute($aAttr=array(), $aAddAttr=array())
    {
        $sResult = '';
        $aAttr = self::attrMerge($aAttr, $aAddAttr);

        foreach ($aAttr as $attr=>$value) {

            if ($attr == 'value') {
                $value = self::entities($value);
            }

            $sResult .= $attr . '="' . $value . '" ';

        }

        return ' ' . $sResult;
    }

    /**
     * 특수문자에 대해 HTML 엔터티로 변환
     * 파라미터가 배열로 들어오는 경우는 각 원소까지 모두 변환
     *
     * @param mixed $mValue
     * @return mixed
     */
    protected static function entities($mValue)
    {
        if (is_array($mValue)) {
            foreach ($mValue as $key => $val) {
                $mValue[$key] = self::entities($val);
            }

            return $mValue;
        }

        $mValue = htmlspecialchars($mValue);

        return $mValue;
    }

}
